package com.fzu.geometa.validate.service;

import com.fzu.geometa.rpc.ValidateRequest;
import com.fzu.geometa.rpc.ValidateResponse;
import com.fzu.geometa.rpc.ValidateServiceGrpc;
import com.fzu.geometa.validate.listener.ValidateListener;
import io.grpc.stub.StreamObserver;
import org.springframework.stereotype.Service;
import org.testng.ITestListener;
import org.testng.Reporter;
import org.testng.TestNG;
import org.testng.xml.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.fzu.geometa.validate.common.Const.*;
import static com.fzu.geometa.validate.common.Standard.ISO_19123;
import static com.fzu.geometa.validate.common.Standard.ISO_19163;

@Service

public class ValidateServiceImpl extends ValidateServiceGrpc.ValidateServiceImplBase {

    @Override
    public void validate(ValidateRequest request, StreamObserver<ValidateResponse> responseObserver) {
        boolean result = validate(request.getStandard(), request.getGroup(), request.getData());
        ValidateResponse response = ValidateResponse
                .newBuilder()
                .setPassed(result)
                .build();
        responseObserver.onNext(response);
        responseObserver.onCompleted();
    }

    /**
     * 数据验证
     *
     * @param standard 测试标准
     * @param group    测试组
     * @param data     测试数据
     */
    public boolean validate(String standard, String group, String data) {
        TestNG testNG = null;
        switch (standard) {
            case ISO_19163:
                testNG = getTestNG(ISO_19163_VALIDATION_CLASS, group, data);
                break;
            case ISO_19123:
                testNG = getTestNG(ISO_19123_VALIDATION_CLASS, group, data);
                break;
            default:
                return false;
            //throw new RuntimeException("没有找到测试标准");
        }
        testNG.run();
        List<ITestListener> testListeners = testNG.getTestListeners();
        for (ITestListener testListener : testListeners) {
            if (testListener instanceof ValidateListener) {
                ValidateListener validateListener = (ValidateListener) testListener;
                int passed = validateListener.getPassedTests().size();
                int failed = validateListener.getFailedTests().size();
                int skipped = validateListener.getSkippedTests().size();
                Reporter.clear();
                // 有全部都为 0 的情况，所以通过验证时 passed 也不能为 0
                return failed == 0 && skipped == 0 && passed != 0;
            }
        }
        //throw new RuntimeException("没有找到监听器");
        return false;
    }

    private TestNG getTestNG(Class testClass, String testGroup, String data) {
        // 定义测试套件
        XmlSuite suite = new XmlSuite();
        suite.setVerbose(1);
        suite.setFileName("Data validation");

        // 设置参数
        Map<String, String> parameter = new HashMap<>();
        parameter.put("test-data", data);
        suite.setParameters(parameter);

        // 定义测试
        List<XmlTest> tests = new ArrayList<>();
        XmlTest test = new XmlTest(suite);

        // 设置测试组
        XmlGroups group = new XmlGroups();
        XmlRun run = new XmlRun();
        run.onInclude(testGroup);
        group.setRun(run);
        test.setGroups(group);

        // 设置测试类
        List<XmlClass> classes = new ArrayList<>();
        XmlClass xmlClass = new XmlClass(testClass);
        classes.add(xmlClass);
        test.setClasses(classes);

        // 添加测试
        tests.add(test);
        suite.setTests(tests);

        // 设置监听器
        List<String> listeners = new ArrayList<>();
        listeners.add(VALIDATE_LISTENER_CLASS);
        suite.setListeners(listeners);

        System.out.println(suite.toXml());

        // 添加测试套件
        TestNG testNG = new TestNG();
        testNG.setCommandLineSuite(suite);

        // 不启用默认监听类
        testNG.setUseDefaultListeners(false);

        // 返回 TestNG 类
        return testNG;
    }
}
